/* test_threads_func_uthread_exit():
	A test for uthread_exit(). Test the regular case + the case where the main
	thread is calling the function (tested on a child-proccess made by 'fork()'.

	* Regular case: Thread 0 creats thread 1, 2. Both 1,2 do uthread_exit().

*/


#include <assert.h>
#include <stdio.h>
#include <stdbool.h>

#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

#include "test_general.h"
#include "user_threads.h"

bool test_threads_func_uthread_exit();

#define THREADS_NUM 3


static int thread1_start_routine(void * param) {
	TEST_ASSERT( 53 == (*((int*)param)) );

	TEST_ASSERT (uthread_self() == 1);

	thread_ok[1] = true;
	uthread_exit(861);
	TEST_ASSERT(false);
}

static int thread2_start_routine(void * param) {
	TEST_ASSERT( 53 == (*((int*)param)) );

	TEST_ASSERT (uthread_self() == 2);

	thread_ok[2] = true;
	uthread_exit(1432);
	TEST_ASSERT(false);
}


bool test_threads_func_uthread_exit()
{
	init_individual_test();

	int tmp;

	if (initilize_uthread_in_each_test) {
		tmp = uthread_init();
		TEST_ASSERT(tmp == UTHREAD_SUCCESS);
	}

	/* Checking special case: */
	pid_t forked_id = fork();
	if (forked_id == 0) {
		uthread_exit(19);
		assert(false);
	}
	pid_t child = wait(&tmp);
	TEST_ASSERT (child == forked_id);
	TEST_ASSERT (WIFEXITED(tmp));
	TEST_ASSERT(WEXITSTATUS(tmp) == 19);

	int FiftyThree = 53;

	thread_id threads[THREADS_NUM];
	threads[0] = uthread_self();

	threads[1] = uthread_create(thread1_start_routine, &FiftyThree);
	TEST_ASSERT(threads[1] == 1);

	threads[2] = uthread_create(thread2_start_routine, &FiftyThree);
	TEST_ASSERT(threads[2] == 2);

	int tmp2;

	tmp = uthread_join(threads[1],&tmp2);
	TEST_ASSERT(UTHREAD_SUCCESS == tmp);
	TEST_ASSERT(861 == tmp2);

	tmp = uthread_join(threads[2],&tmp2);
	TEST_ASSERT(UTHREAD_SUCCESS == tmp);
	TEST_ASSERT(1432 == tmp2);

	thread_ok[0] = true;
	TEST_ASSERT(are_all_threads_ok(THREADS_NUM));

	return true;
}
